package top.xtcoder.jdcbase.base.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 随机生成类
 * <p>Title RandomUtil.java </p>
 * <p>Description  </p>
 *
 * @author lusifercoder
 * @version 1.0.0
 * @date 2019/7/18 0:27
 */
public class RandomUtil {

    private static Logger logger = LoggerFactory.getLogger(RandomUtil.class);

    /**
     * 获取UUID
     *
     * @return
     */
    public static String getUUID() {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid;
    }

    /**
     * 返回十位数的随机字符串
     *
     * @return
     */
    public static String getTenNumber() {
        final int COUNT = 10;
        Random random = new Random();
        int num = random.nextInt(1000000000);
        String value = String.valueOf(num);
        String tenNum = "";
        if (value.length() < COUNT) {
            int len = COUNT - value.length();
            StringBuffer sb = new StringBuffer("");
            for (int i = 0; i < len; i++) {
                sb.append("0");
            }
            tenNum = sb + value;
        } else {
            tenNum = value;
        }
        return tenNum;
    }

    /**
     * 15位数id生成
     *
     * @return
     */
    public static long getId() {
        // 取当前时间的长整形值包含毫秒
        long millis = System.currentTimeMillis();
        // 加上两位随机数  // 155214256129649
        Random random = ThreadLocalRandom.current();
        int end2 = random.nextInt(99);
        // 如果不足两位前面补0
        String str = millis + String.format("%02d", end2);
        long id = new Long(str);
        return id;
    }

    /**
     * 生成指定数字的字符串
     *
     * @param strLength
     * @return
     */
    public static String randomString(int strLength) {
        Random rnd = ThreadLocalRandom.current();
        StringBuilder ret = new StringBuilder();
        for (int i = 0; i < strLength; i++) {
            ret.append(rnd.nextInt(10));
        }
        return ret.toString();
    }

    private final long id;
    /**
     * 时间起始标记点，作为基准，一般取系统的最近时间
     */
    private final long epoch = 1524291141010L;
    /**
     * 机器标识位数
     */
    private final long workerIdBits = 10L;
    /**
     * 机器ID最大值: 1023
     */
    private final long maxWorkerId = -1L ^ -1L << this.workerIdBits;
    /**
     * 0，并发控制
     */
    private long sequence = 0L;
    /**
     * 毫秒内自增位
     */
    private final long sequenceBits = 12L;

    /**
     * 12
     */
    private final long workerIdShift = this.sequenceBits;
    /**
     * 22
     */
    private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;
    /**
     * 4095,111111111111,12位
     */
    private final long sequenceMask = -1L ^ -1L << this.sequenceBits;
    private long lastTimestamp = -1L;

    /**
     * 雪花算法
     *
     * @param id
     */
    private RandomUtil(long id) {
        if (id > this.maxWorkerId || id < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
        }
        this.id = id;
    }

    /**
     * 获得下一个ID(该方法是线程安全的)
     *
     * @return
     */
    public synchronized long nextId() {
        long timestamp = timeGen();
        if (this.lastTimestamp == timestamp) {
            //如果上一个timestamp与新产生的相等，则sequence加一(0-4095循环); 对新的timestamp，sequence从0开始
            this.sequence = this.sequence + 1 & this.sequenceMask;
            if (this.sequence == 0) {
                // 重新生成timestamp
                timestamp = this.tilNextMillis(this.lastTimestamp);
            }
        } else {
            this.sequence = 0;
        }

        if (timestamp < this.lastTimestamp) {
            logger.error(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
            return -1;
        }

        this.lastTimestamp = timestamp;
        return timestamp - this.epoch << this.timestampLeftShift | this.id << this.workerIdShift | this.sequence;
    }

    private static RandomUtil flowIdWorker = new RandomUtil(1);

    public static RandomUtil getFlowIdInstance() {
        return flowIdWorker;
    }

    /**
     * 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
     */
    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 获得系统当前毫秒数
     */
    private static long timeGen() {
        return System.currentTimeMillis();
    }

    /**
     * 获取18位数不重复id
     *
     * @return
     */
    public static long getSystemId() {
        return RandomUtil.getFlowIdInstance().nextId();
    }
    
    public static String getOrderId() {
        return RandomUtil.getFlowIdInstance().nextId() + randomString(6) + "";
    }

    public static void main(String[] args) {
        System.out.println("id====" + getOrderId());
        System.out.println("字符串===" + randomString(10));
    }
}
